package edu.server.dominio;

import java.util.LinkedList;
import java.util.List;

import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;

import edu.server.repositorio.ClaseEquipoPatron;
import edu.server.repositorio.ComponentePatron;
import edu.server.repositorio.EquipoPatron;
import edu.server.repositorio.ListaDeMateriales;
import edu.server.repositorio.RenglonListaMateriales;
import edu.server.repositorio.RenglonListaMaterialesId;
import edu.server.repositorio.SubclaseEquipoPatron;
import edu.server.util.HibernateUtil;
import edu.shared.DTO.ComponentePatronDTO;
import edu.shared.DTO.EquipoPatronDTO;

public class Ingenieria {
	
	public Ingenieria() {
		
	}
	
	/**
	 * Método que busca todas las clases de equipo patrón.
	 * @return lista de clases de equipo patrón.
	 */
	@SuppressWarnings("unchecked")
	public List<ClaseEquipoPatron> buscarClasesEquipoPatron() {
		
		List<ClaseEquipoPatron> listaClasesEquipoPatron;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		listaClasesEquipoPatron = sess.createQuery("FROM ClaseEquipoPatron C " +
												   "ORDER BY C.codigoClaseEquipoPatron ASC").list();
		
		sess.close();
		
		return listaClasesEquipoPatron;	
	}

	/**
	 * Método que busca todas las subclases de equipo patrón para la clase especificada.
	 * @param codigoClaseEquipoPatron
	 * @return lista de subclases de equipo patrón.
	 */
	@SuppressWarnings("unchecked")
	public List<SubclaseEquipoPatron> buscarSubclasesEquipoPatron(int codigoClaseEquipoPatron) {

		List<SubclaseEquipoPatron> listaSubclasesEquipoPatron;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();			
				
		listaSubclasesEquipoPatron = sess.createQuery("FROM SubclaseEquipoPatron S " +
													  "WHERE S.id.codigoClaseEquipoPatron = " + codigoClaseEquipoPatron + 
													  " ORDER BY S.id.codigoClaseEquipoPatron, S.id.codigoSubclaseEquipoPatron ASC").list();
		
		sess.close();
	
		return listaSubclasesEquipoPatron;
	}
	
	/**
	 * Método que busca todos los equipos patrón existentes y los ordena.
	 * @return todos los equipos patrón.
	 */
	@SuppressWarnings("unchecked")
	public List<EquipoPatron> buscarEquiposPatron() {
		
		List<EquipoPatron> listaEquiposPatron;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		listaEquiposPatron = sess.createQuery("FROM EquipoPatron E WHERE activo = true ORDER BY E.subclaseEquipoPatron.id.codigoClaseEquipoPatron ASC").list();
		
		//Inicializo todos los equipos patrón.
		for (EquipoPatron equipoPatron : listaEquiposPatron) {
			Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
			Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		}
		
		sess.close();
		
		return listaEquiposPatron;	
	}
	
	/**
	 * Método que busca todos los equipos patrón que existen en almacén. Recordar que pueden estar activos o no.
	 * @return todos los equipos patrón.
	 */
	@SuppressWarnings("unchecked")
	public List<EquipoPatron> buscarEquiposPatronEnAlmacen() {
		
		List<EquipoPatron> listaEquiposPatron;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		listaEquiposPatron = sess.createQuery("FROM EquipoPatron E WHERE cantidadDisponible > 0 ORDER BY E.subclaseEquipoPatron.id.codigoClaseEquipoPatron ASC").list();
		
		//Inicializo todos los equipos patrón.
		for (EquipoPatron equipoPatron : listaEquiposPatron) {
			Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
			Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		}
		
		sess.close();
		
		return listaEquiposPatron;	
	}

	/**
	 * Método que busca todas las versiones para el equipo patrón especificado
	 * @param codigoClase
	 * @param codigoSubclase
	 * @param plano
	 * @return lista con los equipos patrón en todas sus versiones
	 */
	@SuppressWarnings("unchecked")
	public List<EquipoPatron> buscarEquipoPatronVersiones(int codigoClase, int codigoSubclase, int plano) {
	
		List<EquipoPatron> listaVersionesEquipoPatron;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
				
		// se buscan todas las versiones para el equipo patrón especificado.
		listaVersionesEquipoPatron = sess.createQuery("FROM EquipoPatron E " +
													  " WHERE activo = true " +
													  " AND E.subclaseEquipoPatron.id.codigoClaseEquipoPatron = " + codigoClase +
													  " AND E.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron = " + codigoSubclase +
													  " AND E.plano = " + plano).list();
		
		// se inicializan todos los equipos patrón.
		for (EquipoPatron equipoPatron : listaVersionesEquipoPatron) {
			Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
			Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		}
		
		sess.close();
		
		return listaVersionesEquipoPatron;	
	}

	@SuppressWarnings("unchecked")
	public List<ComponentePatron> buscarComponentesPatron() {

		List<ComponentePatron> listaComponentePatron;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();			
		
		listaComponentePatron = sess.createQuery("FROM ComponentePatron C WHERE activo = true ORDER BY C.id ASC").list();
		
		//Inicializo todos los componentes patrón.
		for (ComponentePatron componentePatron : listaComponentePatron) {
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		}
		
		sess.close();
	
		return listaComponentePatron;
	}
	
	/**
	 * Método que busca los componentes patrón que existen en almacén. Considerar que los componentes pueden estar activos o no.
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<ComponentePatron> buscarComponentesPatronEnAlmacen() {

		List<ComponentePatron> listaComponentePatron;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();			
		
		listaComponentePatron = sess.createQuery("FROM ComponentePatron C WHERE cantidadDisponible > 0 ORDER BY C.id ASC").list();
		
		//Inicializo todos los componentes patrón.
		for (ComponentePatron componentePatron : listaComponentePatron) {
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		}
		
		sess.close();
	
		return listaComponentePatron;
	}
	
	@SuppressWarnings("unchecked")
	public List<ComponentePatron> buscarComponentesPatron(int codigoClase, int codigoSubclase) {
		
		List<ComponentePatron> listaComponentePatron;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		//Busco todos los componentes patrón que tengan el mismo código de clase y subclase que me llega, y los ordeno por esos campos.
		listaComponentePatron = sess.createQuery("FROM ComponentePatron C WHERE C.subclaseEquipoPatron.id.codigoClaseEquipoPatron = " + codigoClase +
				" AND C.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron = " + codigoSubclase + 
				" ORDER BY C.subclaseEquipoPatron.id.codigoClaseEquipoPatron, C.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron," +
				" C.codigoComponente, C.codigoSubcomponente ASC").list();
		
		//Inicializo todos los componentes patrón.
		for (ComponentePatron componentePatron : listaComponentePatron) {
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		}
		
		sess.close();
		
		return listaComponentePatron;
	}
	
	
	/**
	 * Método que busca todos los componentes patrón en su última versión que están activos.
	 * @return lista de componentes patrón.
	 */
	@SuppressWarnings("unchecked")
	public List<ComponentePatron> buscarComponentesPatronUltimaVersionActivos() {
	
		List<ComponentePatron> componentesPatronUltimaVersion = new LinkedList<ComponentePatron>();
		List<Object[]> planosComponentesPatron;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		//Busco todos los componentes patrón, y los ordeno por clase y subclase.
		planosComponentesPatron = sess.createQuery("SELECT DISTINCT C.subclaseEquipoPatron.id.codigoClaseEquipoPatron, " +
								"C.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron, " +
								"C.codigoComponente, " +
								"C.codigoSubcomponente, " + 
								"C.plano " + 
								"FROM ComponentePatron C " +
								"WHERE C.activo = true").list();
		
		for (Object[] componentePatron : planosComponentesPatron) {
			componentesPatronUltimaVersion.add(buscarComponentePatronUltimaVersion((int) componentePatron[0], (int) componentePatron[1], (int) componentePatron[2], (int) componentePatron[3], (int) componentePatron[4]));
		}
		
		for (ComponentePatron componentePatron : componentesPatronUltimaVersion) {
			
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		}
		
		sess.close();
	
		return componentesPatronUltimaVersion;
	}
	
	/**
	 * Método que busca todos los componentes patrón en su última versión.
	 * Método que busca todos los componentes patrón en su última versión, activos e inactivos.
	 * @return lista de componentes patrón.
	 */
	@SuppressWarnings("unchecked")
	public List<ComponentePatron> buscarComponentesPatronUltimaVersion() {
	
		List<ComponentePatron> componentesPatronUltimaVersion = new LinkedList<ComponentePatron>();
		List<Object[]> planosComponentesPatron;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		//Busco todos los componentes patrón, y los ordeno por clase y subclase.
		planosComponentesPatron = sess.createQuery("SELECT DISTINCT C.subclaseEquipoPatron.id.codigoClaseEquipoPatron, " +
								"C.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron, " +
								"C.codigoComponente, " +
								"C.codigoSubcomponente, " + 
								"C.plano " + 
								"FROM ComponentePatron C").list();
		
		for (Object[] componentePatron : planosComponentesPatron) {
			componentesPatronUltimaVersion.add(buscarComponentePatronUltimaVersion((int) componentePatron[0], (int) componentePatron[1], (int) componentePatron[2], (int) componentePatron[3], (int) componentePatron[4]));
		}
		
		for (ComponentePatron componentePatron : componentesPatronUltimaVersion) {
			
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		}
		
		sess.close();
	
		return componentesPatronUltimaVersion;
	}
	
	/**
	 * Método que busca todos los componentes patrón en su última versión, de una clase determinada, activos e inactivos.
	 * @return lista de componentes patrón.
	 */
	@SuppressWarnings("unchecked")
	public List<ComponentePatron> buscarComponentesPatronUltimaVersion(int codigoClase) {
	
		List<ComponentePatron> componentesPatronUltimaVersion = new LinkedList<ComponentePatron>();
		List<Object[]> planosComponentesPatron;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		//Busco todos los componentes patrón de la clase especificada, y los ordeno por clase y subclase.
		planosComponentesPatron = sess.createQuery("SELECT DISTINCT C.subclaseEquipoPatron.id.codigoClaseEquipoPatron, " +
								"C.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron, " +
								"C.codigoComponente, " +
								"C.codigoSubcomponente, " + 
								"C.plano " + 
								" FROM ComponentePatron C" +
								" WHERE C.subclaseEquipoPatron.id.codigoClaseEquipoPatron = " + codigoClase).list();
		
		for (Object[] componentePatron : planosComponentesPatron) {
			componentesPatronUltimaVersion.add(buscarComponentePatronUltimaVersion((int) componentePatron[0], (int) componentePatron[1], (int) componentePatron[2], (int) componentePatron[3], (int) componentePatron[4]));
		}
		
		for (ComponentePatron componentePatron : componentesPatronUltimaVersion) {
			
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		}
		
		sess.close();
	
		return componentesPatronUltimaVersion;
	}

	/**
	 * Método que busca todos los componentes patrón en su última versión, de una clase y subclase determinada, activos e inactivos.
	 * @return lista de componentes patrón.
	 */
	@SuppressWarnings("unchecked")
	public List<ComponentePatron> buscarComponentesPatronUltimaVersion(int codigoClase, int codigoSubclase) {
	
		List<ComponentePatron> componentesPatronUltimaVersion = new LinkedList<ComponentePatron>();
		List<Object[]> planosComponentesPatron;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		//Busco todos los componentes patrón de la clase especificada, y los ordeno por clase y subclase.
		planosComponentesPatron = sess.createQuery("SELECT DISTINCT C.subclaseEquipoPatron.id.codigoClaseEquipoPatron, " +
								"C.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron, " +
								"C.codigoComponente, " +
								"C.codigoSubcomponente, " + 
								"C.plano " + 
								" FROM ComponentePatron C" +
								" WHERE C.subclaseEquipoPatron.id.codigoClaseEquipoPatron = " + codigoClase +
								" AND C.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron = " + codigoSubclase).list();
		
		for (Object[] componentePatron : planosComponentesPatron) {
			componentesPatronUltimaVersion.add(buscarComponentePatronUltimaVersion((int) componentePatron[0], (int) componentePatron[1], (int) componentePatron[2], (int) componentePatron[3], (int) componentePatron[4]));
		}
		
		for (ComponentePatron componentePatron : componentesPatronUltimaVersion) {
			
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		}
		
		sess.close();
	
		return componentesPatronUltimaVersion;
	}
	
	/**
	 * Método que busca todos los componentes y subcomponentes patrón en su última versión, de una clase, subclase y componente determinados, activos e inactivos.
	 * @return lista de componentes patrón.
	 */
	@SuppressWarnings("unchecked")
	public List<ComponentePatron> buscarComponentesPatronUltimaVersion(int codigoClase, int codigoSubclase, int codigoComponente) {
	
		List<ComponentePatron> componentesPatronUltimaVersion = new LinkedList<ComponentePatron>();
		List<Object[]> planosComponentesPatron;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		//Busco todos los componentes patrón de la clase especificada, y los ordeno por clase y subclase.
		planosComponentesPatron = sess.createQuery("SELECT DISTINCT C.subclaseEquipoPatron.id.codigoClaseEquipoPatron, " +
								"C.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron, " +
								"C.codigoComponente, " +
								"C.codigoSubcomponente, " + 
								"C.plano " + 
								" FROM ComponentePatron C" +
								" WHERE C.subclaseEquipoPatron.id.codigoClaseEquipoPatron = " + codigoClase +
								" AND C.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron = " + codigoSubclase + 
								" AND C.codigoComponente = " + codigoComponente).list();
		
		for (Object[] componentePatron : planosComponentesPatron) {
			componentesPatronUltimaVersion.add(buscarComponentePatronUltimaVersion((int) componentePatron[0], (int) componentePatron[1], (int) componentePatron[2], (int) componentePatron[3], (int) componentePatron[4]));
		}
		
		for (ComponentePatron componentePatron : componentesPatronUltimaVersion) {
			
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		}
		
		sess.close();
	
		return componentesPatronUltimaVersion;
	}
	
	/**
	 * Método que busca todos los planos del subcomponente patrón especificado en su última versión, de una clase y subclase determinada, activos e inactivos.
	 * @return lista de componentes patrón.
	 */
	@SuppressWarnings("unchecked")
	public List<ComponentePatron> buscarComponentesPatronUltimaVersion(int codigoClase, int codigoSubclase, int codigoComponente, int codigoSubcomponente) {
	
		List<ComponentePatron> componentesPatronUltimaVersion = new LinkedList<ComponentePatron>();
		List<Object[]> planosComponentesPatron;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		//Busco todos los componentes patrón de la clase especificada, y los ordeno por clase y subclase.
		planosComponentesPatron = sess.createQuery("SELECT DISTINCT C.subclaseEquipoPatron.id.codigoClaseEquipoPatron, " +
								"C.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron, " +
								"C.codigoComponente, " +
								"C.codigoSubcomponente, " + 
								"C.plano " + 
								" FROM ComponentePatron C" +
								" WHERE C.subclaseEquipoPatron.id.codigoClaseEquipoPatron = " + codigoClase +
								" AND C.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron = " + codigoSubclase + 
								" AND C.codigoComponente = " + codigoComponente +
								" AND C.codigoSubcomponente = " + codigoSubcomponente).list();
		
		for (Object[] componentePatron : planosComponentesPatron) {
			componentesPatronUltimaVersion.add(buscarComponentePatronUltimaVersion((int) componentePatron[0], (int) componentePatron[1], (int) componentePatron[2], (int) componentePatron[3], (int) componentePatron[4]));
		}
		
		for (ComponentePatron componentePatron : componentesPatronUltimaVersion) {
			
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		}
		
		sess.close();
	
		return componentesPatronUltimaVersion;
	}
	
	@SuppressWarnings("unchecked")
	public ComponentePatron buscarComponentePatronUltimaVersion(int codigoClase, int codigoSubclase, int codigoComponente, int codigoSubcomponente, int plano) {
	
		List<ComponentePatron> componentesPatron;
		ComponentePatron componentePatronMayorVersion = new ComponentePatron();
		int mayorVersion = -1;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		
		componentesPatron = sess.createQuery("FROM ComponentePatron C WHERE C.subclaseEquipoPatron.id.codigoClaseEquipoPatron = " + codigoClase +
				" AND C.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron = " + codigoSubclase +
				" AND C.codigoComponente = " + codigoComponente +
				" AND C.codigoSubcomponente = " + codigoSubcomponente +
				" AND C.plano = " + plano).list();
		
		for (ComponentePatron componentePatron : componentesPatron) {
			
			if (mayorVersion < Integer.parseInt(componentePatron.getNroVersion().substring(1))) {
				mayorVersion = Integer.parseInt(componentePatron.getNroVersion().substring(1));
				componentePatronMayorVersion = componentePatron;
			}
		}
	
		return componentePatronMayorVersion;
	}

	/**
	 * Método que busca el componente patrón especificado en los parámetros.
	 * @param codigoClase
	 * @param codigoSubclase
	 * @param codigoComponente
	 * @param codigoSubcomponente
	 * @param plano
	 * @param version
	 * @return el componente patrón
	 */
	public ComponentePatron buscarComponentePatron(int codigoClase, int codigoSubclase, String version, int codigoComponente, int codigoSubcomponente, int plano) {
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		//Busco el componente patrón
		ComponentePatron componentePatronCompleto = (ComponentePatron) sess.createQuery("FROM ComponentePatron C " +
				"WHERE C.subclaseEquipoPatron.id.codigoClaseEquipoPatron = " + codigoClase +
				" AND C.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron = " + codigoSubclase + 
				" AND C.nroVersion LIKE '" + version + "'" + 
				" AND C.codigoComponente = " + codigoComponente +
				" AND C.codigoSubcomponente = " + codigoSubcomponente +
				" AND C.plano = " + plano).list().get(0);
		
		//Inicializo el componente patrón
		Hibernate.initialize(componentePatronCompleto.getIdComponentePatron());
		Hibernate.initialize(componentePatronCompleto.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
		Hibernate.initialize(componentePatronCompleto.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		Hibernate.initialize(componentePatronCompleto.getListaDeMateriales().getEstado());
		
		sess.close();
		
		return componentePatronCompleto;
	}

	/**
	 * Método para buscar todos los planos de componente patrón.
	 * @return una lista con todos los planos en su última versión de componente patrón existentes ordenados por clase, subclase, componente y subcomponente.
	 */		
	@SuppressWarnings("unchecked")
	public List<ComponentePatron> buscarPlanosComponentePatron(int codigoClase, int codigoSubclase, int codigoComponente, int codigoSubcomponente) {
	
		List<ComponentePatron> componentesPatron;
		LinkedList<ComponentePatron> componentesPatronUltimaVersion = new LinkedList<ComponentePatron>();
		int mayorPlano = -1;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		//Busco todos los componentes patrón que tengan el mismo código de clase y subclase que me llega, y los ordeno por esos campos.
		componentesPatron = sess.createQuery("FROM ComponentePatron C WHERE C.subclaseEquipoPatron.id.codigoClaseEquipoPatron = " + codigoClase +
				" AND C.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron = " + codigoSubclase + 
				" AND C.codigoComponente = " + codigoComponente + " AND C.codigoSubcomponente = " + codigoSubcomponente +
				" AND C.activo = 'True' " +
				" ORDER BY C.subclaseEquipoPatron.id.codigoClaseEquipoPatron, C.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron," +
				" C.codigoComponente, C.codigoSubcomponente ASC").list();
	
		//Inicializo todos los componentes patrón.
		for (ComponentePatron componentePatron : componentesPatron) {
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getId());
			Hibernate.initialize(componentePatron.getSubclaseEquipoPatron().getClaseEquipoPatron());
			Hibernate.initialize(componentePatron.getListaDeMateriales().getEstado());
		}
		
		//Busco cual es el mayor plano que existe para una clase y subclase de componente particular.
		for (ComponentePatron componentePatron : componentesPatron) {
			if (mayorPlano < componentePatron.getPlano()) {
				mayorPlano = componentePatron.getPlano();
			}
		}
		
		//Para todos los planos que existen, busco el componente patrón cuya versión sea la mayor.
		for (int i = 0; i <= mayorPlano; i++) {
			
			ComponentePatron componentePatronMayorVersion = new ComponentePatron();
			componentePatronMayorVersion.setIdComponentePatron(-1);
			
			for (ComponentePatron componentePatron: componentesPatron) {
				
				int mayorVersion = -1;
				
				//Si es el número de plano por el que estamos mirando...
				if (componentePatron.getPlano() == i) {
					
					//...y la version es la mayor hasta el momento...
					if (Integer.parseInt(componentePatron.getNroVersion().substring(1)) > mayorVersion) {
						
						//...conservo este componente patrón como el que tiene la mayor versión, por ahora.
						componentePatronMayorVersion = componentePatron;
						mayorVersion = Integer.parseInt(componentePatron.getNroVersion().substring(1));
					}
				}				
			}
			
			//Guardo el componente patrón de mayor versión para un plano dado en la lista.
			//La comprobación se hace por si no existe un plano "entre medio". Es decir,
			//para los casos en los que, por ejemplo se eliminó el plano 0, y empieza desde el 1.
			if (componentePatronMayorVersion.getIdComponentePatron() != -1)
				componentesPatronUltimaVersion.add(componentePatronMayorVersion);
		}
		
		sess.close();
	
		return componentesPatronUltimaVersion;
	}

	@SuppressWarnings("unchecked")
	public String buscarUltimaVersionEquipoPatron(int codigoClaseEquipoPatron, int codigoSubclaseEquipoPatron, int planoEquipoPatron) {

		List<EquipoPatron> equiposPatron;
		LinkedList<EquipoPatron> equiposPatronFiltrado = new LinkedList<EquipoPatron>();
		int mayorVersion = 0;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		equiposPatron = sess.createQuery("FROM EquipoPatron E").list();
		
		for (EquipoPatron equipoPatron : equiposPatron) {
			
			Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron());
			Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron().getId());
			
			if ((equipoPatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron() == codigoClaseEquipoPatron) &&
					(equipoPatron.getSubclaseEquipoPatron().getId().getCodigoSubclaseEquipoPatron() == codigoSubclaseEquipoPatron) && 
					(equipoPatron.getPlano() == planoEquipoPatron)) {
				equiposPatronFiltrado.add(equipoPatron);
			}
		}
		
		for (EquipoPatron equipoPatron : equiposPatronFiltrado) {
			
			if (mayorVersion < Integer.parseInt(equipoPatron.getNroVersion().substring(1))) {
				mayorVersion = Integer.parseInt(equipoPatron.getNroVersion().substring(1));
			}
			
		}
		
		sess.close();
	
		return "M" + mayorVersion;
	}	
	
	@SuppressWarnings("finally")
	public boolean registrarEquipoPatron(EquipoPatron equipoPatron) {

		boolean resultado = false;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try {
			
			sess.beginTransaction();
			
			// se intenta obtener la clase de equipo patr�n especificada
			ClaseEquipoPatron claseEquipoPatron = (ClaseEquipoPatron) sess.get(ClaseEquipoPatron.class, equipoPatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getCodigoClaseEquipoPatron());
					
			// si no existe, se la guarda en la base de datos
			if (claseEquipoPatron == null) {
				sess.save(equipoPatron.getSubclaseEquipoPatron().getClaseEquipoPatron());
			}								
					
			sess.save(equipoPatron.getSubclaseEquipoPatron());
			
			sess.save(equipoPatron.getListaDeMateriales());		

			sess.save(equipoPatron);			

			sess.getTransaction().commit();

			resultado = true;
			
		} catch (HibernateException he) {
			
			sess.getTransaction().rollback();
			
			resultado = false;
			
		} finally {
			
			return resultado;
		}
	}

	@SuppressWarnings({ "finally", "unchecked" })
	public boolean registrarEquipoPatronNuevoPlanoOVersion(EquipoPatron equipoPatron, int idListaDeMaterialesEquipoBase) {
	
	boolean resultado = false;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try {
			
			sess.beginTransaction();
			
			// se guarda la lista de materiales. Aún falta cargar sus renglones desde el equipo patrón base.
			int idListaMateriales = (Integer) sess.save(equipoPatron.getListaDeMateriales());	
			
			// se guarda el equipo patrón.
			sess.save(equipoPatron);	
					
			// se buscan todos los renglones de la lista de materiales del equipo patrón base.
			
			List<RenglonListaMateriales> listaRenglonListaMateriales = sess.createQuery("FROM RenglonListaMateriales R " +
																						"WHERE R.id.idListaMateriales = " + idListaDeMaterialesEquipoBase).list();
			
			// se guarda una copia de los renglones de la lista de materiales recuperados, para el nuevo plano de equipo.
			
			int idRenglonListaMateriales = 0;
			
			for (RenglonListaMateriales renglon: listaRenglonListaMateriales) {
				
				RenglonListaMateriales nuevoRenglon = new RenglonListaMateriales();
				
				nuevoRenglon.setCantidad(renglon.getCantidad());
				nuevoRenglon.setComponentePatron(renglon.getComponentePatron());
				nuevoRenglon.setEquipoPatron(renglon.getEquipoPatron());
				nuevoRenglon.setId(new RenglonListaMaterialesId(idListaMateriales, idRenglonListaMateriales));
				nuevoRenglon.setMedida1(renglon.getMedida1());
				nuevoRenglon.setMedida2(renglon.getMedida2());
				nuevoRenglon.setProducto(renglon.getProducto());
				
				sess.save(nuevoRenglon);				
				
				idRenglonListaMateriales++;
			}			

			sess.getTransaction().commit();

			resultado = true;
			
		} catch (HibernateException he) {
			
			sess.getTransaction().rollback();
			
			resultado = false;
			
		} finally {
			
			return resultado;
		}
	}

	@SuppressWarnings({ "unchecked", "finally" })
	public boolean registrarComponentePatronNuevoPlanoOVersion(ComponentePatron componentePatron, int idListaMaterialesComponenteBase) {
			
		boolean resultado = false;
			
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try {
			
			sess.beginTransaction();
			
			// se guarda la lista de materiales. Aún falta cargar sus renglones desde el componente patrón base.
			int idListaMateriales = (Integer) sess.save(componentePatron.getListaDeMateriales());	
			
			// se guarda el componente patrón.
			sess.save(componentePatron);	
					
			// se buscan todos los renglones de la lista de materiales del componente patrón base.
			
			List<RenglonListaMateriales> listaRenglonListaMateriales = sess.createQuery("FROM RenglonListaMateriales R " +
																						"WHERE R.id.idListaMateriales = " + idListaMaterialesComponenteBase).list();
			
			// se guarda una copia de los renglones de la lista de materiales recuperados, para el nuevo plano de componente.
			
			int idRenglonListaMateriales = 0;
			
			for (RenglonListaMateriales renglon: listaRenglonListaMateriales) {
				
				RenglonListaMateriales nuevoRenglon = new RenglonListaMateriales();
				
				nuevoRenglon.setCantidad(renglon.getCantidad());
				nuevoRenglon.setComponentePatron(renglon.getComponentePatron());
				nuevoRenglon.setEquipoPatron(renglon.getEquipoPatron());
				nuevoRenglon.setId(new RenglonListaMaterialesId(idListaMateriales, idRenglonListaMateriales));
				nuevoRenglon.setMedida1(renglon.getMedida1());
				nuevoRenglon.setMedida2(renglon.getMedida2());
				nuevoRenglon.setProducto(renglon.getProducto());
				
				sess.save(nuevoRenglon);				
				
				idRenglonListaMateriales++;
			}			

			sess.getTransaction().commit();

			resultado = true;
			
		} catch (HibernateException he) {
			
			sess.getTransaction().rollback();
			
			resultado = false;
			
		} finally {
			
			return resultado;
		}
	}

	@SuppressWarnings("finally")
	public int registrarClaseEquipoPatron(ClaseEquipoPatron claseEquipoPatron) {
	
		int codigoClase = -1;

		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try {
			
			sess.beginTransaction();	
								
			codigoClase = ((ClaseEquipoPatron) sess.save(claseEquipoPatron)).getCodigoClaseEquipoPatron();
	
			sess.getTransaction().commit();
			
		} catch (HibernateException he) {
			
			sess.getTransaction().rollback();
			
		} finally {
			
			return codigoClase;
		}
	}
	
	/**
	 * Método que registra en base de datos el componente pasado como parámetro (que semánticamente puede tratarse tanto de un componente como de un subcomponente.
	 * @param componente
	 * @return id del componente patrón: si éxito
	 * 		   -1: caso contrario
	 */
	@SuppressWarnings("finally")
	public int registrarComponentePatron(ComponentePatron componente) {
	
		int idComponetePatron = -1;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try {
			
			sess.beginTransaction();					
					
			// se crea la lista de materiales en base de datos
			sess.save(componente.getListaDeMateriales());		

			// se guarda el componente
			idComponetePatron = (Integer) sess.save(componente);			

			sess.getTransaction().commit();
			
		} catch (HibernateException he) {
			
			sess.getTransaction().rollback();
			
			idComponetePatron = -1;
			
		} finally {
			
			return idComponetePatron;
		}
	}

	/**
	 * Método que registra el renglón de lista de materiales pasado como parámetro.
	 * @param renglon
	 * @return true: si éxito
	 * 		   false: caso contrario
	 */
	@SuppressWarnings("finally")
	public boolean registrarRenglonListaDeMateriales(RenglonListaMateriales renglon) {
	
		boolean exito = false;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try {
			
			sess.beginTransaction();						

			// se guarda el renglón de lista de materiales.
			sess.save(renglon);			

			sess.getTransaction().commit();
			
			exito = true;
			
		} catch (HibernateException he) {
			
			sess.getTransaction().rollback();
			
			exito = false;
			
		} finally {
			
			return exito;
		}
	}

	@SuppressWarnings("unchecked")
	public List<SubclaseEquipoPatron> buscarSubclasesPorNombreYClase(String nombreSubclase, String codigoClase) {

		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		
		sess.beginTransaction();
		
		List<SubclaseEquipoPatron> listaObjetos = sess.createQuery("FROM SubclaseEquipoPatron S " +
																   "WHERE S.claseEquipoPatron = " + codigoClase +
																   " AND S.nombre LIKE '" + nombreSubclase.toUpperCase() + "'").list();

		sess.close();
		
		return listaObjetos;
	}
	
	/**
	 * Método que busca todos los equipos patrón en su última versión.
	 * @return lista de equipos patrón.
	 */
	@SuppressWarnings("unchecked")
	public List<EquipoPatron> buscarEquiposPatronUltimaVersion() {

		List<EquipoPatron> equiposPatron;
		LinkedList<EquipoPatron> equiposPatronUltimaVersion = new LinkedList<EquipoPatron>();
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		//Busco todos los equipos patrones, y los ordeno por clase y subclase.
		equiposPatron = sess.createQuery("FROM EquipoPatron E" +
										 " WHERE activo = 1 " +
										 " ORDER BY E.subclaseEquipoPatron.id.codigoClaseEquipoPatron, E.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron ASC").list();
		
		//Inicializo todos los equipos patrón.
		for (EquipoPatron equipoPatron : equiposPatron) {
			Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
			Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		}
		
		// se busca el número de clase más alto, que servirá como límite superior para los recorridos.
		int maxCodigoClase = (int) sess.createQuery("SELECT MAX(C.codigoClaseEquipoPatron) " +
													"FROM ClaseEquipoPatron C").list().get(0);
		
		// se busca el número de subclase más alto, que servirá como límite superior para los recorridos (aunque no todas las clases tengan la misma cantidad de subclases).
		int maxCodigoSubclase = (int) sess.createQuery("SELECT MAX(S.id.codigoSubclaseEquipoPatron) " +
													   "FROM SubclaseEquipoPatron S").list().get(0);
				
		// matriz de equipos patrón, donde el número de FILA representa al código de CLASE, y el número de columna al código de SUBCLASE.
		// cada posición de la matriz contiene una lista de los planos del equipo patrón con la clase y subclase especificada.
		// las filas y columnas 0 no se utilizan, para que coincidan las posiciones con los códigos de clase y subclase (que comienzan ambos en 1).
		LinkedList<EquipoPatron>[][] planosEquiposPatron = new LinkedList[maxCodigoClase+1][maxCodigoSubclase+1]; 
		
		// se recorren todos los equipos patrón, y se los va clasificando por código de clase y subclase, dentro de la matriz recién creada.
		for (EquipoPatron equipoPatron: equiposPatron) {
			
			int codigoClase = equipoPatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron();
			int codigoSubclase = equipoPatron.getSubclaseEquipoPatron().getId().getCodigoSubclaseEquipoPatron();
			
			// si aún no se creo una lista en la posición especificada, se la crea.
			if (planosEquiposPatron[codigoClase][codigoSubclase] == null) {
				planosEquiposPatron[codigoClase][codigoSubclase] = new LinkedList<EquipoPatron>();
			}
			
			planosEquiposPatron[codigoClase][codigoSubclase].add(equipoPatron);		
		}
		
		int codigoClase = 1;
		
		// para cada clase. 
		while (codigoClase <= maxCodigoClase) {
			
			int codigoSubclase = 1;
			
			// para cada subclase.
			while (codigoSubclase <= maxCodigoSubclase) {
				
				// si el equipo patrón especificado posee al menos un plano.
				if (planosEquiposPatron[codigoClase][codigoSubclase] != null) {	
					
					// se agregan las últimas versiones de cada plano de este equipo patrón, a la lista general de últimas versiones.
					equiposPatronUltimaVersion.addAll(ultimaVersionDeCadaPlano(planosEquiposPatron[codigoClase][codigoSubclase]));
				}
				
				codigoSubclase++;
			}
			
			codigoClase++;
		}
		
		sess.close();
	
		return equiposPatronUltimaVersion;
	}

	/**
	 * Método que busca todos los equipos patrón de una clase determinada, en su última versión.
	 * @param codigoClase
	 * @return lista de equipos patrón.
	 */
	@SuppressWarnings("unchecked")
	public List<EquipoPatron> buscarEquiposPatronUltimaVersion(int codigoClaseEquipoPatron) {

		List<EquipoPatron> equiposPatron;
		LinkedList<EquipoPatron> equiposPatronUltimaVersion = new LinkedList<EquipoPatron>();
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		//Busco todos los equipos patrones de la clase, y los ordeno por clase y subclase.
		equiposPatron = sess.createQuery("FROM EquipoPatron E " +
										 " WHERE activo = 1 " +
										 " AND E.subclaseEquipoPatron.id.codigoClaseEquipoPatron = " + codigoClaseEquipoPatron +
										 " ORDER BY E.subclaseEquipoPatron.id.codigoClaseEquipoPatron, E.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron ASC").list();
		
		//Inicializo todos los equipos patrón.
		for (EquipoPatron equipoPatron : equiposPatron) {
			Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
			Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		}
				
		// se busca el número de subclase más alto de la clase, que servirá como límite superior para los recorridos.
		int maxCodigoSubclase = (int) sess.createQuery("SELECT MAX(S.id.codigoSubclaseEquipoPatron) " +
													   "FROM SubclaseEquipoPatron S " +
													   "WHERE S.id.codigoClaseEquipoPatron = " + codigoClaseEquipoPatron).list().get(0);
					
		// array de equipos patrón, donde la posición el número de posición representa al código de SUBCLASE.
		// cada posición del array contiene una lista de los planos del equipo patrón con la subclase especificada.
		// la posición 0 no se utiliza, para que coincidan las posiciones con los códigos de subclase (que comienza en 1).
		LinkedList<EquipoPatron>[] planosEquiposPatron = new LinkedList[maxCodigoSubclase+1]; 		
		
		// se recorren todos los equipos patrón, y se los va clasificando por código de clase y subclase, dentro de la matriz recién creada.
		for (EquipoPatron equipoPatron: equiposPatron) {
			
			int codigoSubclase = equipoPatron.getSubclaseEquipoPatron().getId().getCodigoSubclaseEquipoPatron();
			
			// si aún no se creó una lista en la posición especificada, se la crea.
			if (planosEquiposPatron[codigoSubclase] == null) {
				planosEquiposPatron[codigoSubclase] = new LinkedList<EquipoPatron>();
			}
			
			planosEquiposPatron[codigoSubclase].add(equipoPatron);		
		}
		
		int codigoSubclase = 1;
		
		// para cada subclase.
		while (codigoSubclase <= maxCodigoSubclase) {
			
			// si el equipo patrón especificado posee al menos un plano.
			if (planosEquiposPatron[codigoSubclase] != null) {	
				
				// se agregan las últimas versiones de cada plano de este equipo patrón, a la lista general de últimas versiones.
				equiposPatronUltimaVersion.addAll(ultimaVersionDeCadaPlano(planosEquiposPatron[codigoSubclase]));
			}
			
			codigoSubclase++;
		}
		
		sess.close();
	
		return equiposPatronUltimaVersion;
	}
	
	/**
	 * Método para buscar todos los planos de equipo patrón.
	 * @param codigoClaseEquipoPatron
	 * @param codigoSubclaseEquipoPatron
	 * @return una lista con todos los planos de equipo patrón existentes ordenados por clase y subclase que están activos en su última versión.
	 */	
	@SuppressWarnings("unchecked")
	public List<EquipoPatron> buscarPlanosEquipoPatron(int codigoClaseEquipoPatron, int codigoSubclaseEquipoPatron) {
	
		List<EquipoPatron> equiposPatron;
		//LinkedList<EquipoPatron> equiposPatronFiltrado = new LinkedList<EquipoPatron>();
		LinkedList<EquipoPatron> equiposPatronUltimaVersion = new LinkedList<EquipoPatron>();
		int mayorPlano = -1;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		//Busco todos los equipos patrones que tengan el mismo código de clase y subclase que me llega, y los ordeno por esos campos.
		equiposPatron = sess.createQuery("FROM EquipoPatron E WHERE E.subclaseEquipoPatron.id.codigoClaseEquipoPatron = " + codigoClaseEquipoPatron +
				" AND E.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron = " + codigoSubclaseEquipoPatron + 
				" AND E.activo = 1 " + 
				" ORDER BY E.subclaseEquipoPatron.id.codigoClaseEquipoPatron, E.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron ASC").list();
		
		
		//Inicializo todos los equipos patrón.
		for (EquipoPatron equipoPatron : equiposPatron) {
			Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
			Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		}
		
		
		
		
		/*
		equiposPatron = sess.createQuery("FROM EquipoPatron E ORDER BY E.id ASC").list();
		
		for (EquipoPatron equipoPatron : equiposPatron) {
			
			if ((equipoPatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron() == codigoClaseEquipoPatron) &&
					(equipoPatron.getSubclaseEquipoPatron().getId().getCodigoSubclaseEquipoPatron() == codigoSubclaseEquipoPatron)) {
				equiposPatronFiltrado.add(equipoPatron);
			}
		}
		*/
		
		//Busco cual es el mayor plano que existe para una clase y subclase de equipo particular.
		for (EquipoPatron equipoPatron : equiposPatron) {
			if (mayorPlano < equipoPatron.getPlano()) {
				mayorPlano = equipoPatron.getPlano();
			}
		}
		
		//Para todos los planos que existen, busco el equipo patrón cuya versión sea la mayor.
		for (int i = 0; i <= mayorPlano; i++) {
			
			EquipoPatron equipoPatronMayorVersion = new EquipoPatron();
			equipoPatronMayorVersion.setIdEquipoPatron(-1);
			
			for (EquipoPatron equipoPatron: equiposPatron) {
				
				int mayorVersion = -1;
				
				//Si es el número de plano por el que estamos mirando...
				if (equipoPatron.getPlano() == i) {
					
					//...y la version es la mayor hasta el momento...
					if (Integer.parseInt(equipoPatron.getNroVersion().substring(1)) > mayorVersion) {
						
						//...conservo este equipo patrón como el que tiene la mayor versión, por ahora.
						equipoPatronMayorVersion = equipoPatron;
						mayorVersion = Integer.parseInt(equipoPatron.getNroVersion().substring(1));
					}
				}				
			}
			
			//Guardo el equipo patrón de mayor versión para un plano dado en la lista.
			//La comprobación se hace por si no existe un plano "entre medio". Es decir,
			//para los casos en los que, por ejemplo se eliminó el plano 0, y empieza desde el 1.
			if (equipoPatronMayorVersion.getIdEquipoPatron() != -1)
				equiposPatronUltimaVersion.add(equipoPatronMayorVersion);
		}
		
		sess.close();
	
		return equiposPatronUltimaVersion;
	}
	
	
	/**
	 * Método que busca todos los renglones de una lista de materiales.
	 * @param idListaMaterialesEquipoContenedor
	 * @return lista de renglones
	 */
	@SuppressWarnings("unchecked")
	public List<RenglonListaMateriales> buscarRenglonesListaMateriales(int idListaMaterialesEquipoContenedor) {
	
		List<RenglonListaMateriales> listaRenglones;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();			
				
		listaRenglones = sess.createQuery("FROM RenglonListaMateriales R " +
										  "WHERE R.id.idListaMateriales = " + idListaMaterialesEquipoContenedor + 
										  " ORDER BY R.id.idRenglonListaMateriales ASC").list();
		
		sess.close();
	
		return listaRenglones;
	}

	/**
	 * Método que recibe una lista de equipos patrón de una misma clase y subclase, y devuele una lista de equipos patrón con la última versión de cada plano.
	 * @param equiposPatron
	 */
	private List<EquipoPatron> ultimaVersionDeCadaPlano(List<EquipoPatron> equiposPatron) {

		List<EquipoPatron> ultimaVersionDeCadaPlano = new LinkedList<EquipoPatron>();
		int mayorPlano = -1;
		
		//Busco cuál es el mayor plano que existe para una clase y subclase de equipo particular.
		for (EquipoPatron equipoPatron : equiposPatron) {
			if (mayorPlano < equipoPatron.getPlano()) {
				mayorPlano = equipoPatron.getPlano();
			}
		}
		
		//Para todos los planos que existen, busco el equipo patrón cuya versión sea la mayor.
		for (int i = 0; i <= mayorPlano; i++) {
			
			EquipoPatron equipoPatronMayorVersion = new EquipoPatron();
			equipoPatronMayorVersion.setIdEquipoPatron(-1);
			
			for (EquipoPatron equipoPatron: equiposPatron) {
				
				int mayorVersion = -1;
				
				//Si es el número de plano por el que estamos mirando...
				if (equipoPatron.getPlano() == i) {
					
					//...y la version es la mayor hasta el momento...
					if (Integer.parseInt(equipoPatron.getNroVersion().substring(1)) > mayorVersion) {
						
						//...conservo este equipo patrón como el que tiene la mayor versión, por ahora.
						equipoPatronMayorVersion = equipoPatron;
						mayorVersion = Integer.parseInt(equipoPatron.getNroVersion().substring(1));
					}
				}				
			}
			
			//Guardo el equipo patrón de mayor versión para un plano dado en la lista.
			//La comprobación se hace por si no existe un plano "entre medio". Es decir,
			//para los casos en los que, por ejemplo se eliminó el plano 0, y empieza desde el 1.
			if (equipoPatronMayorVersion.getIdEquipoPatron() != -1)
				ultimaVersionDeCadaPlano.add(equipoPatronMayorVersion);
		}
		
		return ultimaVersionDeCadaPlano;
	}

	/**
	 * Método que busca el equipo patrón especificado en los parámetros.
	 * @param codigoClase
	 * @param codigoSubclase
	 * @param plano
	 * @param version
	 * @return el equipo patrón
	 */
	public EquipoPatron buscarEquipoPatron(int codigoClase, int codigoSubclase, int plano, String version) {

		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		
		sess.beginTransaction();
		
		EquipoPatron equipoPatron = (EquipoPatron) sess.createQuery("FROM EquipoPatron E " +
															   	    "WHERE E.subclaseEquipoPatron.id.codigoClaseEquipoPatron = " + codigoClase +
																    " AND E.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron = " + codigoSubclase +
																    " AND E.plano = " + plano +
																    " AND E.nroVersion LIKE '" + version + "'").list().get(0);

		Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
		Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		Hibernate.initialize(equipoPatron.getListaDeMateriales().getEstado());
		
		sess.close();
		
		return equipoPatron;
	}
	
	/**
	 * Método que actualiza el equipo patrón pasado como parámetro, en su atributo "cantidad".
	 * @param equipoPatronDTO
	 * @return 1: éxito
	 * 		   0: fallo
	 */
	@SuppressWarnings("finally")
	public int actualizarCantidadEquipoPatron(EquipoPatron equipoPatron) {

		int resultado = 0;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try {
			
			sess.beginTransaction();
			
			String hql = "UPDATE EquipoPatron set cantidadDisponible = :cantidadDisponible " + 
						 "WHERE idEquipoPatron = :idEquipoPatron";
			
			Query query = sess.createQuery(hql);
			
			query.setParameter("cantidadDisponible", equipoPatron.getCantidadDisponible());
			query.setParameter("idEquipoPatron", equipoPatron.getIdEquipoPatron());
			
			resultado = query.executeUpdate();	

			sess.getTransaction().commit();
			
		} catch (HibernateException he) {
			
			sess.getTransaction().rollback();
			
			resultado = 0;
			
		} finally {
			
			return resultado;
		}
	}
	
	/**
	 * Método que actualiza el componente patrón pasado como parámetro, en su atributo "cantidad".
	 * @param equipoPatronDTO
	 * @return 1: éxito
	 * 		   0: fallo
	 */
	@SuppressWarnings("finally")
	public int actualizarCantidadComponentePatron(ComponentePatron componentePatron) {

		int resultado = 0;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try {
			
			sess.beginTransaction();
			
			String hql = "UPDATE ComponentePatron set cantidadDisponible = :cantidadDisponible " + 
						 "WHERE idComponentePatron = :idComponentePatron";
			
			Query query = sess.createQuery(hql);
			
			query.setParameter("cantidadDisponible", componentePatron.getCantidadDisponible());
			query.setParameter("idComponentePatron", componentePatron.getIdComponentePatron());
			
			resultado = query.executeUpdate();	

			sess.getTransaction().commit();
			
		} catch (HibernateException he) {
			
			sess.getTransaction().rollback();
			
			resultado = 0;
			
		} finally {
			
			return resultado;
		}
	}
	
	
	/**
	 * Método que actualiza el equipo patrón pasado como parámetro, en sus atributos "descripción técnica", "punto pedido" y "lote".
	 * @param equipoPatronDTO
	 * @return 1: éxito
	 * 		   0: caso contrario
	 */
	@SuppressWarnings("finally")
	public int actualizarEquipoPatron(EquipoPatronDTO equipoPatronDTO) {

		int filasActualizadas = 0;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try {
			
			sess.beginTransaction();						
			
			String hql = "UPDATE EquipoPatron set descripcionTecnica = :descripcionTecnica, puntoPedido = :puntoPedido, lote = :lote " + 
						 "WHERE idEquipoPatron = :idEquipoPatron";
			
			Query query = sess.createQuery(hql);
			
			query.setParameter("descripcionTecnica", equipoPatronDTO.getDescripcionTecnica());
			query.setParameter("puntoPedido", equipoPatronDTO.getPuntoPedido());
			query.setParameter("lote", equipoPatronDTO.getLote());
			query.setParameter("idEquipoPatron", equipoPatronDTO.getIdEquipoPatron());
			
			filasActualizadas = query.executeUpdate();	

			sess.getTransaction().commit();
			
		} catch (HibernateException he) {
			
			sess.getTransaction().rollback();
			
			filasActualizadas = 0;
			
		} finally {
			
			return filasActualizadas;
		}
	}

	/**
	 * Método que actualiza el componente patrón pasado como parámetro, en sus atributos "descripción técnica", "punto pedido" y "lote".
	 * @param equipoPatronDTO
	 * @return 1: éxito
	 * 		   0: caso contrario
	 */
	@SuppressWarnings("finally")
	public int actualizarComponentePatron(ComponentePatronDTO componentePatron) {
		
		int filasActualizadas = 0;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try {
			
			sess.beginTransaction();						
			
			String hql = "UPDATE ComponentePatron set descripcionTecnica = :descripcionTecnica, puntoPedido = :puntoPedido, lote = :lote " + 
						 "WHERE idComponentePatron = :idComponentePatron";
			
			Query query = sess.createQuery(hql);
			
			query.setParameter("descripcionTecnica", componentePatron.getDescripcionTecnica());
			query.setParameter("puntoPedido", componentePatron.getPuntoPedido());
			query.setParameter("lote", componentePatron.getLote());
			query.setParameter("idComponentePatron", componentePatron.getIdComponentePatron());
			
			filasActualizadas = query.executeUpdate();	

			sess.getTransaction().commit();
			
		} catch (HibernateException he) {
			
			sess.getTransaction().rollback();
			
			filasActualizadas = 0;
			
		} finally {
			
			return filasActualizadas;
		}
	}

	@SuppressWarnings("finally")
	public boolean eliminarEquipoPatron(int idEquipoPatron) {
		
		int filasActualizadas = 0;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try {
			
			sess.beginTransaction();						
			
			String hql = "UPDATE EquipoPatron set activo = :activo " + 
						 "WHERE idEquipoPatron = :idEquipoPatron";
			
			Query query = sess.createQuery(hql);
			
			query.setParameter("activo", false);
			query.setParameter("idEquipoPatron", idEquipoPatron);
			
			filasActualizadas = query.executeUpdate();	

			sess.getTransaction().commit();
			
		} catch (HibernateException he) {
			
			sess.getTransaction().rollback();
			
			filasActualizadas = 0;
			
		} finally {
			
			if (filasActualizadas == 1) {
				return true;
			}
			
			else {
				return false;
			}
		}
	}

	@SuppressWarnings("finally")
	public boolean eliminarComponentePatron(int idComponentePatron) {
		
		int filasActualizadas = 0;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try {
			
			sess.beginTransaction();						
			
			String hql = "UPDATE ComponentePatron set activo = :activo " + 
						 "WHERE idComponentePatron = :idComponentePatron";
			
			Query query = sess.createQuery(hql);
			
			query.setParameter("activo", false);
			query.setParameter("idComponentePatron", idComponentePatron);
			
			filasActualizadas = query.executeUpdate();	

			sess.getTransaction().commit();
			
		} catch (HibernateException he) {
			
			sess.getTransaction().rollback();
			
			filasActualizadas = 0;
			
		} finally {
			
			if (filasActualizadas == 1) {
				return true;
			}
			
			else {
				return false;
			}
		}
	}

	@SuppressWarnings("unchecked")
	public List<EquipoPatron> buscarPlanosEquipoPatronActivosEInactivos(int codigoClase, int codigoSubclase) {

		List<EquipoPatron> equiposPatron;
		//LinkedList<EquipoPatron> equiposPatronFiltrado = new LinkedList<EquipoPatron>();
		LinkedList<EquipoPatron> equiposPatronUltimaVersion = new LinkedList<EquipoPatron>();
		int mayorPlano = -1;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		//Busco todos los equipos patrones que tengan el mismo código de clase y subclase que me llega, y los ordeno por esos campos.
		equiposPatron = sess.createQuery("FROM EquipoPatron E WHERE E.subclaseEquipoPatron.id.codigoClaseEquipoPatron = " + codigoClase +
				" AND E.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron = " + codigoSubclase + 
				" ORDER BY E.subclaseEquipoPatron.id.codigoClaseEquipoPatron, E.subclaseEquipoPatron.id.codigoSubclaseEquipoPatron ASC").list();
		
		
		//Inicializo todos los equipos patrón.
		for (EquipoPatron equipoPatron : equiposPatron) {
			Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
			Hibernate.initialize(equipoPatron.getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
		}
		
		
		
		
		/*
		equiposPatron = sess.createQuery("FROM EquipoPatron E ORDER BY E.id ASC").list();
		
		for (EquipoPatron equipoPatron : equiposPatron) {
			
			if ((equipoPatron.getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron() == codigoClaseEquipoPatron) &&
					(equipoPatron.getSubclaseEquipoPatron().getId().getCodigoSubclaseEquipoPatron() == codigoSubclaseEquipoPatron)) {
				equiposPatronFiltrado.add(equipoPatron);
			}
		}
		*/
		
		//Busco cual es el mayor plano que existe para una clase y subclase de equipo particular.
		for (EquipoPatron equipoPatron : equiposPatron) {
			if (mayorPlano < equipoPatron.getPlano()) {
				mayorPlano = equipoPatron.getPlano();
			}
		}
		
		//Para todos los planos que existen, busco el equipo patrón cuya versión sea la mayor.
		for (int i = 0; i <= mayorPlano; i++) {
			
			EquipoPatron equipoPatronMayorVersion = new EquipoPatron();
			equipoPatronMayorVersion.setIdEquipoPatron(-1);
			
			for (EquipoPatron equipoPatron: equiposPatron) {
				
				int mayorVersion = -1;
				
				//Si es el número de plano por el que estamos mirando...
				if (equipoPatron.getPlano() == i) {
					
					//...y la version es la mayor hasta el momento...
					if (Integer.parseInt(equipoPatron.getNroVersion().substring(1)) > mayorVersion) {
						
						//...conservo este equipo patrón como el que tiene la mayor versión, por ahora.
						equipoPatronMayorVersion = equipoPatron;
						mayorVersion = Integer.parseInt(equipoPatron.getNroVersion().substring(1));
					}
				}				
			}
			
			//Guardo el equipo patrón de mayor versión para un plano dado en la lista.
			//La comprobación se hace por si no existe un plano "entre medio". Es decir,
			//para los casos en los que, por ejemplo se eliminó el plano 0, y empieza desde el 1.
			if (equipoPatronMayorVersion.getIdEquipoPatron() != -1)
				equiposPatronUltimaVersion.add(equipoPatronMayorVersion);
		}
		
		sess.close();
	
		return equiposPatronUltimaVersion;
	}
	
	/**
	 * Método que busca una lista de materiales por su id.
	 * @param idListaMateriales
	 * @return la lista de materiales.
	 */
	public ListaDeMateriales buscarListaDeMateriales(int idListaMateriales) {
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		
		sess.beginTransaction();
		
		ListaDeMateriales listaDeMateriales = (ListaDeMateriales) sess.createQuery("FROM ListaDeMateriales LM " +
															   	    "WHERE LM.idListaMateriales = " + idListaMateriales).list().get(0);

		Hibernate.initialize(listaDeMateriales.getEstado());
		Hibernate.initialize(listaDeMateriales.getRenglonListaMaterialeses());
		
		for (RenglonListaMateriales renglon : listaDeMateriales.getRenglonListaMaterialeses()) {
			
			if (renglon.getEquipoPatron() != null) {
				Hibernate.initialize(renglon.getEquipoPatron().getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
				Hibernate.initialize(renglon.getEquipoPatron().getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
				Hibernate.initialize(renglon.getEquipoPatron().getListaDeMateriales().getEstado());
				Hibernate.initialize(renglon.getEquipoPatron().getListaDeMateriales().getIdListaMateriales());
			}
			
			else if (renglon.getComponentePatron() != null) {
				Hibernate.initialize(renglon.getComponentePatron().getSubclaseEquipoPatron().getId().getCodigoClaseEquipoPatron());
				Hibernate.initialize(renglon.getComponentePatron().getSubclaseEquipoPatron().getClaseEquipoPatron().getNombre());
				Hibernate.initialize(renglon.getComponentePatron().getListaDeMateriales().getEstado());
				Hibernate.initialize(renglon.getComponentePatron().getListaDeMateriales().getIdListaMateriales());
			}
			
			else {
				Hibernate.initialize(renglon.getProducto().getElementoProducto().getClaseProducto().getCodigoClaseProducto());
				Hibernate.initialize(renglon.getProducto().getElementoProducto().getClaseProducto().getNombre());
				Hibernate.initialize(renglon.getProducto().getMaterialProducto().getNombre());
				Hibernate.initialize(renglon.getProducto().getMedidaFijaProducto().getMedida());
			}
		}
		
		sess.close();
		
		return listaDeMateriales;	
	}
	
	/**
	 * Método que busca el estado de una lista de materiales.
	 * @return el estado.
	 */
	public String buscarEstadoListaMateriales(int idListaMateriales) {
		
		ListaDeMateriales listaMateriales;
		
		Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
		sess.beginTransaction();
		
		listaMateriales = (ListaDeMateriales) sess.createQuery("FROM ListaDeMateriales LM " +
					"WHERE LM.idListaMateriales = " + idListaMateriales).list().get(0);
		
		sess.close();
		
		return listaMateriales.getEstado();	
	}
	
	//Retorna el número de orden de pedido con el cual se genero.
	public int registrarListaMateriales(ListaDeMateriales listaDeMateriales) {
				
		int idListaMateriales = 0;
		int idRenglon = 1;
		
		Session sesion = HibernateUtil.getSessionFactory().getCurrentSession();
		
		try {			
			sesion.beginTransaction();
						
			sesion.update(listaDeMateriales);
			idListaMateriales = listaDeMateriales.getIdListaMateriales();
			
			List<RenglonListaMateriales> renglones = obtenerRenglonesListaMateriales(idListaMateriales, sesion);
			
			for (RenglonListaMateriales renglon: renglones) {
				sesion.delete(renglon);
			}
			
			//Guardamos cada renglón de la orden de pedido.
			for (RenglonListaMateriales renglon: listaDeMateriales.getRenglonListaMaterialeses()) {
				renglon.setId(new RenglonListaMaterialesId(idListaMateriales, idRenglon));
				sesion.save(renglon);				
				idRenglon++;
			}
			
			sesion.getTransaction().commit();
		}
		catch (HibernateException he) {
			he.printStackTrace();
			sesion.getTransaction().rollback();
		}
		
		return idListaMateriales;
	}
	
	/**
	 * Función que retorna todos los renglones de una lista de materiales.
	 * @param idListaMateriales
	 * @return lista de renglones de una lista de materiales.
	 */
	@SuppressWarnings("unchecked")
	public List<RenglonListaMateriales> obtenerRenglonesListaMateriales(int idListaMateriales, Session sesion) {
		
		List<RenglonListaMateriales> renglones = new LinkedList<RenglonListaMateriales>();
		
		renglones = sesion.createQuery("FROM RenglonListaMateriales R WHERE R.id.idListaMateriales = " + idListaMateriales).list();
		
		return renglones;
	}
}
